package cn.yunbamboos.rest.service.core;

import cn.yunbamboos.rest.service.IFilterExecute;
import cn.yunbamboos.rest.service.IRestService;
import cn.yunbamboos.rest.service.RestServiceExchange;
import cn.yunbamboos.rest.service.filter.FilterChain;
import cn.yunbamboos.rest.service.filter.GlobalRestServiceFilter;
import cn.yunbamboos.rest.service.filter.RestServiceFilter;
import cn.yunbamboos.rest.service.handler.FilteringHandler;
import org.springframework.context.ApplicationContext;

import java.util.ArrayList;
import java.util.List;

public class FilterExecute implements IFilterExecute {

    private final ApplicationContext applicationContext;
    private final List<RestServiceFilter> globalFilters;

    public FilterExecute(ApplicationContext applicationContext, List<GlobalRestServiceFilter> globalFilters) {
        this.applicationContext = applicationContext;
        this.globalFilters = convert(globalFilters);
    }

    @Override
    public void before(IRestService service) {
        DefaultRestServiceExchange exchange = new DefaultRestServiceExchange(service);
        Class<? extends RestServiceFilter>[] filters = service.filters();

        List<RestServiceFilter> restServiceFilterList = new ArrayList<>(globalFilters);
        for (Class<? extends RestServiceFilter> type : filters) {
            RestServiceFilter serviceFilter = applicationContext.getBean(type);
            restServiceFilterList.add(serviceFilter);
        }
        new FilteringHandler().handle(restServiceFilterList, exchange);
    }

    @Override
    public void after(IRestService service) {
        DefaultRestServiceExchange exchange = new DefaultRestServiceExchange(service);
        Class<? extends RestServiceFilter>[] filters = service.afterFilters();
        List<RestServiceFilter> restServiceFilterList = new ArrayList<>();
        for (Class<? extends RestServiceFilter> type : filters) {
            RestServiceFilter serviceFilter = applicationContext.getBean(type);
            restServiceFilterList.add(serviceFilter);
        }
        new FilteringHandler().handle(restServiceFilterList, exchange);
    }

    private List<RestServiceFilter> convert(List<GlobalRestServiceFilter> globalFilters) {
        List<RestServiceFilter> list = new ArrayList<>();
        for (GlobalRestServiceFilter globalFilter : globalFilters) {
            list.add(new DefaultRestServiceFilter(globalFilter));
        }
        return list;
    }

    public static class DefaultRestServiceFilter implements RestServiceFilter {

        private final GlobalRestServiceFilter filter;

        public DefaultRestServiceFilter(GlobalRestServiceFilter filter) {
            this.filter = filter;
        }

        @Override
        public int order() {
            return filter.order();
        }

        @Override
        public void filter(RestServiceExchange exchange, FilterChain chain) {
            filter.filter(exchange, chain);
        }
    }

}
